package com.chaos.generator;

import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;

import java.util.*;

/**
 * @author Jacky
 * @date 2020/2/25 0:15
 */
public class CodeHelper {
    //默认使用 chaos 库，关闭后使用项目名称
    public static boolean isUseDefaultDbName = false;
    // 是否仅覆盖实体（适用于字段变更场景）
    public static boolean isOnlyOverrideEntity = false;
    // 服务基础文件
    public static boolean isOverrideBase = false;
    // 是否 api 分包（适用于分布式场景）
    public static boolean isApiSplit = true;


    public static String projectPath = null;
    public static String projectApiPath = null;
    public static String projectSaasPath = null;
    public static String moduleName = null;
    public static String projectName = null;

    public static String scanner(String tip) {
        Scanner scanner = new Scanner(System.in);
        StringBuilder help = new StringBuilder();
        help.append("请输入" + tip + "：");
        System.out.println(help.toString());
        if (scanner.hasNext()) {
            String ipt = scanner.next();
            if (StringUtils.isNotBlank(ipt)) {
                return ipt;
            }
        }
        throw new MybatisPlusException("请输入正确的" + tip + "！");
    }

    public static FileOutConfig FileOutConfig_api(String tp, String prefix, String suffix) {
        return new FileOutConfig(tp) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                return projectApiPath + prefix + tableInfo.getEntityName() + suffix;
            }
        };
    }

    public static FileOutConfig FileOutConfig_service(String tp, String prefix, String suffix) {
        return new FileOutConfig(tp) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                return projectPath + prefix + tableInfo.getEntityName() + suffix;
            }
        };
    }

    public static FileOutConfig FileOutConfig_saas(String tp, String prefix, String suffix) {
        return new FileOutConfig(tp) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                String table = tableInfo.getEntityName();
                String lowerCaseFirstLetter = table.substring(0, 1).toLowerCase() + table.substring(1);
                String path = projectSaasPath + prefix + lowerCaseFirstLetter + suffix;
                System.out.println("tp: " + tp);
                System.out.println("path: " + path);
                return path;
            }
        };
    }

    public static FileOutConfig FileOutConfig_service(String tp, String file) {
        return new FileOutConfig(tp) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                return projectPath + file;
            }
        };
    }

    public static List<FileOutConfig> initData() {
        List<FileOutConfig> focList = new ArrayList<>();


        getServiceTp(focList);


        getSassTp(focList);

        return focList;
    }

    private static void getSassTp(List<FileOutConfig> focList) {
        //saas 端代码
        String tp_saas = "templates-saas/";
        focList.add(FileOutConfig_saas(tp_saas + "datatypes/data.d.ts.ftl", "datatypes/", "/data.d.ts"));

        if (!isOnlyOverrideEntity) {
            focList.add(FileOutConfig_saas(tp_saas + "pages/index.ftl", "pages/", "/index.tsx"));
            focList.add(FileOutConfig_saas(tp_saas + "services/index.ts.ftl", "services/", "/index.ts"));
            focList.add(FileOutConfig_saas(tp_saas + "pages/components/UpdateForm.ftl", "pages/", "/components/UpdateForm.tsx"));
        }
    }


    private static void getServiceTp(List<FileOutConfig> focList) {

        String tp = "templates-service/";

        FileOutConfig dataFileOutConfig = null;
        if (isApiSplit) {
            dataFileOutConfig = FileOutConfig_api(tp + "java/data/data.ftl", "/src/main/java/com/chaos/" + moduleName + "/api/data/", "Data" + StringPool.DOT_JAVA);
        } else {
            dataFileOutConfig = FileOutConfig_service(tp + "java/data/data.ftl", "/src/main/java/com/chaos/" + moduleName + "/api/data/", "Data" + StringPool.DOT_JAVA);
        }
        focList.add(dataFileOutConfig);
        focList.add(FileOutConfig_service(tp + "java/entity/model.ftl", "/src/main/java/com/chaos/" + moduleName + "/entity/", StringPool.DOT_JAVA));

        if (!isOnlyOverrideEntity) {
            focList.add(FileOutConfig_service(tp + "mapper/mapper.xml.ftl", "/src/main/resources/mapper/", "Mapper" + StringPool.DOT_XML));
            focList.add(FileOutConfig_service(tp + "java/service/service.ftl", "/src/main/java/com/chaos/" + moduleName + "/service/", "Service" + StringPool.DOT_JAVA));
            focList.add(FileOutConfig_service(tp + "java/mapper/mapper.ftl", "/src/main/java/com/chaos/" + moduleName + "/mapper/", "Mapper" + StringPool.DOT_JAVA));
            focList.add(FileOutConfig_service(tp + "java/controller/controller.ftl", "/src/main/java/com/chaos/" + moduleName + "/controller/", "Controller" + StringPool.DOT_JAVA));
        }

        if (isOverrideBase) {
            focList.add(FileOutConfig_service(tp + "pom.xml.ftl", "/pom" + StringPool.DOT_XML));
            focList.add(FileOutConfig_service(tp + "ChaosServiceApplication.java.ftl", "/src/main/java/com/chaos/" + moduleName + "/Chaos" + projectName + "ServiceApplication" + StringPool.DOT_JAVA));
            focList.add(FileOutConfig_service(tp + "bootstrap.yml.ftl", "/src/main/resources/bootstrap.yml"));
        }

    }


    public static void initGlobalConfig(AutoGenerator mpg) {
        // 全局配置
        GlobalConfig gc = new GlobalConfig();
        buildPath();
        gc.setOutputDir(projectPath + "/src/main/java");
        gc.setFileOverride(true);
        gc.setAuthor("Jacky.Cui");
        gc.setOpen(true);
        mpg.setGlobalConfig(gc);
    }

    private static void buildPath() {

        /***
         * 项目默认路径
         * chaos 以chaos 为根目录，saas 以chaos-saas 为根目录（chaos 项目同级）
         * 其他项目 比如 big 项目为例，以 chaos-big 为根目录（），big-saas 为 saas 根目录（big 同级）
         */
        String bathPath;
        String bathSaasPath;
        if (moduleName.equals("chaos")) {
            bathPath = "./";
            bathSaasPath = "./../chaos-saas/";
        } else {
            bathPath = "./../../" + moduleName+"/";
            bathSaasPath = "./../../"+moduleName+"/" + moduleName + "-saas/";
        }

        projectPath = bathPath + "chaos-" + moduleName + "/chaos-" + moduleName + "-service";
        projectApiPath = bathPath + "chaos-" + moduleName + "/chaos-" + moduleName + "-api";
        projectSaasPath = bathSaasPath + "src/";
    }

    public static void initPackageConfig(AutoGenerator mpg) {
        // 包配置
        final PackageConfig pc = new PackageConfig();
        pc.setModuleName(CodeHelper.moduleName);
        pc.setParent("com.chaos");
        mpg.setPackageInfo(pc);

    }

    public static void initDataSource(AutoGenerator mpg) {
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setDriverName("com.mysql.cj.jdbc.Driver");
        String dbName = moduleName;
        if (isUseDefaultDbName) {
            dbName = "chaos";
        }

        dsc.setUrl("jdbc:mysql://127.0.0.1:3306/" + dbName + "?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai");
        dsc.setUsername("root");
        dsc.setPassword("root");
        mpg.setDataSource(dsc);

    }


    public static void initInjectionConfig(AutoGenerator mpg) {
        // 自定义配置
        InjectionConfig cfg = new InjectionConfig() {
            @Override
            public void initMap() {
                Map<String, Object> params = new HashMap<String, Object>();
                params.put("rootPath", "com.chaos." + moduleName);
                params.put("projectName", projectName);
                params.put("moduleName", moduleName);
                this.setMap(params);
            }
        };

        cfg.setFileOutConfigList(CodeHelper.initData());
        mpg.setCfg(cfg);
    }

    public static void initTemplateConfig(AutoGenerator mpg) {
        // 配置模板
        TemplateConfig templateConfig = new TemplateConfig();
        templateConfig.setEntity(null);
        templateConfig.setMapper(null);
        templateConfig.setService(null);
        templateConfig.setServiceImpl(null);
        templateConfig.setController(null);
        templateConfig.setXml(null);
        mpg.setTemplate(templateConfig);
    }

    public static void initStrategyConfig(AutoGenerator mpg) {
        // 策略配置
        StrategyConfig strategy = new StrategyConfig();
        strategy.setNaming(NamingStrategy.underline_to_camel);
        strategy.setColumnNaming(NamingStrategy.underline_to_camel);
        strategy.setSuperEntityClass("com.chaos.framework.model.entity.IdModel");
        strategy.setEntityLombokModel(true);
        strategy.setRestControllerStyle(true);
        // 公共父类
        strategy.setSuperControllerClass("com.chaos.framework.starter.base.BaseController");
        strategy.setInclude(CodeHelper.scanner("表名，多个英文逗号分割").split(","));
        strategy.setControllerMappingHyphenStyle(true);
        //strategy.setTablePrefix(pc.getModuleName() + "_");
        mpg.setStrategy(strategy);

    }
}
